﻿using System.Collections.Generic;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using EPiServer.Core;
using EPiServer.UI.WebControls;
using EPiServer.Web.PropertyControls;
using TemplateFoundation.Configuration;
using TemplateFoundation.Core;
using TemplateFoundation.CustomProperties;
using TemplateFoundation.Tags;

namespace TemplateFoundation.WebControls.PropertyControls
{
    /// <summary>
    /// Property control for the PropertyTags custom property type
    /// </summary>
    public class PropertyTagsControl : PropertyDataControl
    {
        private ToolButton _addButton;
        private ToolButton _removeButton;
        private HtmlSelect _tagList;
        private HtmlInputText _tagNameTextBox;
        private HtmlGenericControl _tagListContainer;

        private PropertyTags PropertyTags
        {
            get { return (base.PropertyData as PropertyTags); }
        }

        /// <summary>
        /// Gets or sets the edit control.
        /// </summary>
        /// <value>The edit control.</value>
        protected HiddenField EditControl { get; set; }

        /// <summary>
        /// Gets whether this control supports on-page edit
        /// </summary>
        public override bool SupportsOnPageEdit
        {
            get { return false; }
        }

        /// <summary>
        /// Saves the property value
        /// </summary>
        public override void ApplyEditChanges()
        {
            SetValue(EditControl.Value);
        }

        /// <summary>
        /// Creates controls for modifying tags
        /// </summary>
        public override void CreateEditControls()
        {
            // Create hidden field for storing a pipe-separated list of added tags
            EditControl = new HiddenField();
            Controls.Add(EditControl);

            // Verify required site settings have been set
            if (PageReference.IsNullOrEmpty(Settings.Instance.TagsContainer))
            {
                Controls.Add(new Literal { Text = string.Format("{0}: {1}", LanguageManager.Instance.Translate("/common/disabled"), LanguageManager.Instance.Translate("/properties/propertytags/containernotset")) });
                return;
            }

            if (!Settings.Instance.TagPageTypeId.HasValue)
            {
                Controls.Add(new Literal { Text = string.Format("{0}: {1}", LanguageManager.Instance.Translate("/common/disabled"), LanguageManager.Instance.Translate("/properties/propertytags/pagetypenotset")) });
                return;
            }

            // Create list for displaying added tags
            _tagList = new HtmlSelect
                           {
                               Size = 4,
                               Multiple = true
                           };
            _tagList.Attributes.Add("class", "episize240");

            // Add added tags to listbox and to the hidden data field
            var tags = new List<string>();
            foreach (Tag tag in PropertyTags.Tags)
            {
                _tagList.Items.Add(new ListItem(tag.Name));
                tags.Add(tag.Name);
            }
            EditControl.Value = string.Join("|", tags.ToArray());

            // Create container for added tags and remove button so they can be hidden when no tags are added
            _tagListContainer = new HtmlGenericControl("div");

            // Hide tag list if no tags have been added
            if (_tagList.Items.Count == 0)
            {
                _tagListContainer.Attributes.Add("style", "display: none;");
            }

            // Create remove button
            _removeButton = new ToolButton
                                   {
                                       SkinID = "delete",
                                       GeneratesPostBack = false,
                                       Text = LanguageManager.Instance.Translate("/properties/propertytags/remove")
                                   };

            // Add container with tag list and remove button
            _tagListContainer.Controls.Add(_tagList);
            _tagListContainer.Controls.Add(new Literal { Text = "<div style=\"margin-top: 0.5em\" class=\"epi-buttonDefault\">" });

            _tagListContainer.Controls.Add(_removeButton);
            _tagListContainer.Controls.Add(new Literal { Text = "</div>" });
            Controls.Add(_tagListContainer);

            _tagNameTextBox = new HtmlInputText
                              {
                                  MaxLength = 20,
                              };

            _tagNameTextBox.Attributes.Add("class", "episize240");

            Controls.Add(_tagNameTextBox);

            Controls.Add(new Literal {Text = "<div style=\"margin-top: 0.5em\" class=\"epi-buttonDefault\">"});

            _addButton = new ToolButton
                             {
                                 Enabled = !PageReference.IsNullOrEmpty(Settings.Instance.TagsContainer),
                                 SkinID = "add",
                                 GeneratesPostBack = false,
                                 Text = LanguageManager.Instance.Translate("/properties/propertytags/add"),
                             };

            Controls.Add(_addButton);

            Controls.Add(new Literal {Text = "</div>"});
        }

        /// <summary>
        /// Creates a control for rendering a list of tags
        /// </summary>
        public override void CreateDefaultControls()
        {
            if (RenderType == RenderType.Default)
            {
                var ul = new HtmlGenericControl("ul");

                ul.Attributes.Add("class", (CssClass + " tags").Trim());

                foreach (Tag tag in PropertyTags.Tags)
                {
                    var li = new HtmlGenericControl("li");

                    li.Attributes.Add("class", tag.PageCount.ToString());

                    string link = PageReference.IsNullOrEmpty(tag.PageLink) ? "#" : tag.PageLink.GetPage().LinkURL;

                    li.Controls.Add(new HtmlAnchor {HRef = link, InnerText = tag.Name});

                    ul.Controls.Add(li);
                }

                if (ul.Controls.Count > 0)
                {
                    Controls.Add(ul);
                }
            }
        }

        /// <summary>
        /// Adds embedded JavaScript for the tags control
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected override void OnPreRender(System.EventArgs e)
        {
            base.OnPreRender(e);

            // Add JavaScript for buttons (if in edit mode)

            if (RenderType!=RenderType.Edit)
            {
                return;
            }

            if (_addButton != null && _removeButton != null) // Added because of reported bug #29358 causing NullReferenceException
            {
                _removeButton.OnClientClick = @"var list = document.getElementById('" + _tagList.ClientID + @"');
                                           if(list.selectedIndex>=0)
                                           {
                                                list.remove(list.selectedIndex);
                                           }
                                           var valueField = document.getElementById('" + EditControl.ClientID + @"');
                                           valueField.value='';
                                           for (var i=0; i<list.length; i++)
                                           {
                                                if(valueField.value=='') { valueField.value=list.options[i].text; }
                                                    else { valueField.value = valueField.value + '|' + list.options[i].text; }
                                                  }
                                                  if(list.length==0) { document.getElementById('" + _tagListContainer.ClientID + @"').style.cssText = 'display:none'; }";

                _addButton.OnClientClick = @"var option = document.createElement('option');
                                          var valueField = document.getElementById('" + EditControl.ClientID + @"');
                                          var tagBox = document.getElementById('" + _tagNameTextBox.ClientID + @"');
                                          if(tagBox.value=='') { return; }
                                          var list = document.getElementById('" + _tagList.ClientID + @"');
                                          for (var i=0; i<list.length; i++){
                                            if(list.options[i].text==tagBox.value)
                                            {
                                                return;
                                            }
                                          }
                                          option.text = tagBox.value;
                                          try 
                                          {
                                            list.add(option, null);
                                          }
                                          catch(ex)
                                          {
                                            list.add(option);
                                          }
                                          tagBox.value = '';
                                          valueField.value='';
                                          for (var i=0; i<list.length; i++) {
                                            if(valueField.value=='') { valueField.value=list.options[i].text; }
                                            else { valueField.value = valueField.value + '|' + list.options[i].text; }
                                          }
                                          document.getElementById('" + _tagListContainer.ClientID + @"').style.cssText = 'display:inline';";
            }
        }
    }
}